#include <tsin/library/BulletReflectEvent.hpp>

#include <tsin/library/BulletDieOutEvent.hpp>

#include <tsin/runtime/GameRuntime.hpp>
#include <tsin/runtime/BulletRuntime.hpp>

#include <tsin/library/GameViewport.hpp>

#include <cstring>
#define _USE_MATH_DEFINES
#include <cmath>

using namespace tsin;

BulletReflectEvent::BulletReflectEvent(bool d)
        : BulletEvent(d), borders(REFLECT_LEFT | REFLECT_RIGHT | REFLECT_TOP), times(1)
{
}

void BulletReflectEvent::init(int borders, int times)
{
        this->borders = borders;
        this->times = times;
}

void BulletReflectEvent::reinit()
{
        int arg1 = arguments[0]->getInt();
        int arg2 = arguments[1]->getInt();

        switch(nrArguments) {
        case 0:
                init();
                break;
        case 1:
                if (strcmp(desp, "M") == 0)
                        init(arg1);
                break;
        case 2:
                if (strcmp(desp, "MN") == 0)
                        init(arg1, arg2);
                break;
        }
}

DynamicObject *BulletReflectEvent::copy()
{
        return DynamicObject::copy(new BulletReflectEvent(true));
}

bool BulletReflectEvent::trigger(BulletRuntime &bullet, void *)
{
        return bullet.stage == BULLET_STAGE_LIVE;
}

BulletEvent *BulletReflectEvent::handle(BulletRuntime &bullet, void *)
{
        float borderX = bullet.residence->width()/2;
        float borderY = bullet.residence->height()/2;

        if (bullet.x < -borderX) {
                if ((borders & REFLECT_LEFT) && times > 0) {
                        bullet.x = - 2*borderX - bullet.x;
                        bullet.direction = -M_PI/2 - (bullet.direction - M_PI/2);
                        times --;
                } else {
                        times = 0;
                }
        } else if (bullet.x > borderX) {
                if ((borders & REFLECT_RIGHT) && times > 0) {
                        bullet.x = 2*borderX - bullet.x;
                        bullet.direction = M_PI/2 - (bullet.direction + M_PI/2);
                        times --;
                } else {
                        times = 0;
                }
        }

        if (bullet.y < -borderY) {
                if ((borders & REFLECT_BOTTOM) && times > 0) {
                        bullet.y = - 2*borderY - bullet.y;
                        bullet.direction = M_PI - bullet.direction;
                        times --;
                } else {
                        times = 0;
                }
        } else if (bullet.y > borderY) {
                if ((borders & REFLECT_TOP) && times > 0) {
                        bullet.y = 2*borderY - bullet.y;
                        bullet.direction = - (bullet.direction - M_PI);
                        times --;
                } else {
                        times = 0;
                }
        }

        if (times <= 0) {
                return next();
        }

        return this;
}

DynamicObject *bindReflectEvent()
{
        return new BulletReflectEvent(true);
}
